package com.skivingcloud.validation.conf;

import com.skivingcloud.common.utils.ReturnT;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;

/**
 * @author hushouquan
 * 统一异常处理接口
 */
@RestControllerAdvice
public class ExceptionHandlerConfig{
    
    private static final Logger log = LoggerFactory.getLogger(ExceptionHandlerConfig.class);
    
    /**
     * validation参数校验异常 统一处理
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public ReturnT<String> exceptionHandler500(BindException e){
        StringBuilder stringBuilder = new StringBuilder();
        for (ObjectError error : e.getAllErrors()) {
            stringBuilder.append(error.getDefaultMessage());
        }
        return ReturnT.error(stringBuilder.toString());
    }
    
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public ReturnT<String> exceptionHandler500(ConstraintViolationException e){
        StringBuilder stringBuilder = new StringBuilder();
        for (ConstraintViolation<?> error : e.getConstraintViolations()) {
            PathImpl pathImpl = (PathImpl) error.getPropertyPath();
            stringBuilder.append(error.getMessage());
        }
        return ReturnT.error(stringBuilder.toString());
    }
    
    @ExceptionHandler(SQLException.class)
    public ReturnT<String> mySqlException(SQLException e){
        log.error("数据库操作异常", e);
        if (e instanceof SQLIntegrityConstraintViolationException){
            return ReturnT.error("数据唯一键重复，操作失败");
        }
        return  ReturnT.error("数据库异常，操作失败");
    }
    
    @ExceptionHandler(AccessDeniedException.class)
    public ReturnT<String> accessDeniedException(AccessDeniedException e){
        return ReturnT.error(403,"抱歉，您没有此操作权限");
    }
    /**
     * 未知异常 统一处理
     */
    @ExceptionHandler(value =Exception.class)
    @ResponseBody
    public ReturnT<String> exceptionHandler(Exception e){
        log.error("未知系统错误", e);
        return ReturnT.error(ReturnT.FAIL_CODE, "未知系统错误", e.getMessage());
    }
    
    @InitBinder
    public void dataBind(WebDataBinder binder){
        //WebDataBinder是用来绑定请求参数到指定的属性编辑器，可以继承WebBindingInitializer
        //来实现一个全部controller共享的dataBiner Java代码
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }
}
